package com.yixin.aps.config;


import com.yixin.aps.common.Coordinate;
import com.yixin.aps.common.JsonUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import redis.clients.jedis.*;
import redis.clients.util.SafeEncoder;

import java.io.*;
import java.util.*;

/**
 * 就一个小Demo 随便写下
 * @author bigsea
 *
 */
@Component
public class RedisClient {

    private Logger logger = LoggerFactory.getLogger(RedisClient.class);

    @Autowired
    private JedisPool pool;
    private  Integer defaultExpire=Integer.MAX_VALUE;

    public  Integer getDefaultExpire() {
        return defaultExpire;
    }

    public  void setDefaultExpire(String defaultExpire) {
        //默认300秒
        this.defaultExpire = Integer.valueOf(defaultExpire);
    }

    /**
     * 获得redis连接
     *
     * @return
     */
    private Jedis getJedis() {
        return pool.getResource();
    }

    /**
     * 释放redis连接
     *
     * @param redis
     */
    private  void freeConn(Jedis redis) {
        pool.returnResource(redis);
    }

    /**
     * 清空单个缓存对象
     *
     * @param key
     * @return 1:成功 0:失败
     */
    public  Long delete(String key) {
        Jedis jedis = null;
        Long result = null;
        try {
            jedis = getJedis();
            result = jedis.del(key);
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            if (jedis != null) {
                freeConn(jedis);
            }
        }
        return result;
    }

    /**
     * @author chengangyx
     * @注释：判断是否存在key
     */
    public  boolean existsKey(String key) {
        Jedis jedis = null;
        boolean result = false;
        try {
            jedis = getJedis();
            result = jedis.exists(key);
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return result;
    }

    /**
     * 查看缓存类型
     *
     * @param key
     * @return
     */
    public  String type(String key) {
        Jedis jedis = null;
        String result = null;
        try {
            jedis = getJedis();
            result = jedis.type(key);
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            if (jedis != null) {
                freeConn(jedis);
            }
        }
        return result;
    }

    /**
     * 查看缓存过期时间
     *
     * @param key
     * @return 秒
     */
    public  Long expireTime(String key) {
        Jedis jedis = null;
        Long result = null;
        try {
            jedis = getJedis();
            result = jedis.ttl(key);
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            if (jedis != null) {
                freeConn(jedis);
            }
        }
        return result;
    }

    /**
     * 读取字符串缓存
     *
     * @param key
     * @return
     */
    public  String get(String key) {
        Jedis jedis = null;
        String result = null;
        try {
            jedis = getJedis();
            result = jedis.get(key);

        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            if (jedis != null) {
                freeConn(jedis);
            }
        }
        return result;
    }
    /**
     * 设置字符串的值并返回存储在键上的旧值
     * @param key
     * @param value
     * @return
     * add 2016.12.21
     */
    public  String getSet(String key, String value){
        Jedis jedis = null;
        String result = null;
        try {
            jedis = getJedis();
            result = jedis.getSet(key, value);
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            if (jedis != null) {
                freeConn(jedis);
            }
        }
        return result;
    }
    /**
     * 如果键已经存在不执行操作，SET if Not eXists
     * @param key
     * @param value
     * @return 1 if the key was set 0 if the key was not set
     * 		add 2016.12.21
     */
    public  Long SetNX(String key, String value){
        Jedis jedis = null;
        Long result;
        try {
            jedis = getJedis();
            result = jedis.setnx(key, value);
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            if (jedis != null) {
                freeConn(jedis);
            }
        }
        return result;
    }

    /**
     * 获取可序列化的对象
     * @param key
     * @return
     */
    @SuppressWarnings("unchecked")
    public  <T extends Serializable> T getT(String key)
    {
        byte[] c= get(key.getBytes());
        T unserializable = (T)unserializable(c);
        return unserializable;
    }

    /**
     * 读取序列化缓存
     *
     * @param key
     * @return
     */
    private  byte[] get(byte[] key) {
        Jedis jedis = null;
        byte[] result = null;
        try {
            jedis = getJedis();
            result = jedis.get(key);

        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            if (jedis != null) {
                freeConn(jedis);
            }
        }
        return result;
    }


    /**
     * 添加简单对象缓存
     *
     * @param key
     * @param value
     * @return
     */
    public  String set(String key, String value) {
        return set(key, value, getDefaultExpire());
    }

    /**
     * 添加简单对象缓存
     *
     * @param key
     * @param value
     * @param second
     *            过期时间（秒）
     * @return
     */
    public  String set(String key, String value, Integer second) {
        if (value == null) {
            return null;
        }
        Jedis jedis = null;
        String result = null;
        try {
            jedis = getJedis();
            result = jedis.setex(key, second, value.toString());
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            if (jedis != null) {
                freeConn(jedis);
            }
        }
        return result;
    }

    /***/

    /**
     * 添加可序列化对象缓存
     *
     * @param key
     * @param value
     * @return
     */
    public  <T extends Serializable> String setT(String key, T value) {
        return setT(key, value, getDefaultExpire());
    }

    /**
     * 添加可序列化对象缓存
     *
     * @param key
     * @param value
     * @param second
     *            过期时间（秒）
     * @return
     */
    public  <T extends Serializable> String setT(String key, T value, Integer second) {
        if (value == null) {
            return null;
        }
        Jedis jedis = null;
        String result = null;
        try {
            jedis = getJedis();
            result = jedis.setex(key.getBytes(), second, serializable(value));
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            if (jedis != null) {
                freeConn(jedis);
            }
        }
        return result;
    }

    /**
     * 将可序列化对象添加进set缓存
     *
     * @param key
     * @param v
     * @return
     */
    public <T extends Serializable> Long sadd(String key, T v) {
        Jedis redis = null;
        try {
            redis = getJedis();
            return redis.sadd(SafeEncoder.encode(key), serializable(v));
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        } finally {
            if (null != redis)
                freeConn(redis);
        }
    }

    /**
     * 讲可序列化对象添加到list缓存尾部
     *
     * @param key
     * @param v
     * @return
     */
    public  <T extends Serializable> Long rpush(String key, T v) {
        Jedis redis = null;
        try {
            redis = getJedis();
            return redis.rpush(SafeEncoder.encode(key), serializable(v));
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        } finally {
            if (null != redis)
                freeConn(redis);
        }
    }
    /**
     * 讲可序列化对象添加到list缓存 头部
     *
     * @param key
     * @param v
     * @return
     */
    public  <T extends Serializable> Long lpush(String key, T v) {
        Jedis redis = null;
        try {
            redis = getJedis();
            return redis.lpush(SafeEncoder.encode(key), serializable(v));
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        } finally {
            if (null != redis)
                freeConn(redis);
        }
    }

    /**
     * 取出某个区间内的list缓存
     *
     * @param key
     * @param start
     * @param end
     * @return
     */
    public  <T extends Serializable> List<T> getListByIndex(String key, int start, int end) {
        Jedis redis = null;
        try {
            redis = getJedis();
            Long isExists = redis.ttl(key);
            if (isExists == -2 // 数据不存在时
                    || isExists == 0) { // 数据失效时
                redis.del(key); // 清空这个key的数据
                return null;
            }
            return unserializable(redis.lrange(SafeEncoder.encode(key), start, end));
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        } finally {
            if (null != redis)
                freeConn(redis);
        }
    }

    /**
     * 取出整个list缓存
     * @param key
     * @param <T>
     * @return
     */
    public  <T extends Serializable> List<T> getListAll(String key) {
        Jedis redis = null;
        try {
            redis = getJedis();
            Long isExists = redis.ttl(key);
            if (isExists == -2 // 数据不存在时
                    || isExists == 0) { // 数据失效时
                redis.del(key); // 清空这个key的数据
                return null;
            }
            Long size = redis.llen(key);
            return unserializable(redis.lrange(SafeEncoder.encode(key), 0, size));
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        } finally {
            if (null != redis)
                freeConn(redis);
        }
    }

    /**
     * 取出整个hashMap
     * @param key
     * @param <T>
     * @return
     */
    public  <T extends Serializable> Map<String, T> getHash(final String key) {

        Jedis redis = null;
        try {
            redis = getJedis();
            Long isExists = redis.ttl(key);
            if (isExists == -2 // 数据不存在时
                    || isExists == 0) { // 数据失效时
                redis.del(key); // 清空这个key的数据
                return null;
            }
            return unserializable(redis.hgetAll(SafeEncoder.encode(key)));
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        } finally {
            if (null != redis)
                freeConn(redis);
        }
    }

    /**
     * 将hash保存进redis
     *
     * @param key
     * @param map
     * @return
     */
    public  <T extends Serializable> void setHash(final String key, Map<String, T> map) {
        setHash(key, map, getDefaultExpire());
    }

    /**
     * 将hash保存进redis
     *
     * @param key
     * @param map
     * @param seconds
     *            秒
     * @return
     */
    public  <T extends Serializable> void setHash(final String key, Map<String, T> map, Integer seconds) {
        Jedis redis = null;
        try {
            redis = getJedis();
            byte[] in_key = SafeEncoder.encode(key);
            for (Map.Entry<String, T> entry : map.entrySet()) {
                redis.hset(in_key, SafeEncoder.encode(entry.getKey()), serializable(entry.getValue()));
            }
            redis.expire(in_key, seconds);
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        } finally {
            if (null != redis)
                freeConn(redis);
        }
    }

    /**
     * 将list保存进redis
     *
     * @param key
     * @param list
     */
    public  <T extends Serializable> void setList(final String key, List<T> list) {
        setList(key, list, getDefaultExpire());
    }

    /**
     * 将list保存进redis
     *
     * @param key
     * @param list
     * @param seconds
     *            秒
     */
    public  <T extends Serializable> void setList(final String key, List<T> list, Integer seconds) {
        Jedis redis = null;
        try {
            redis = getJedis();
            byte[] in_key = SafeEncoder.encode(key);
            for (T t : list) {
                redis.rpush(in_key, serializable(t));
            }
            redis.expire(in_key, seconds);
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        } finally {
            if (null != redis)
                freeConn(redis);
        }
    }

    /**
     * 返回redis列表 key 中的第一个元素。不移除。
     * @param key
     * @return
     */
    public <T extends Serializable> T getList(String key) {

        Jedis redis =null;
        try {
            redis = getJedis();
            byte[] in_key = SafeEncoder.encode(key);
            return unserializable(redis.lindex(in_key, 0));
        } finally {
            if (null != redis)
                freeConn(redis);
        }
    }
    /**
     * 移除并返回redis列表 key 中的第一个元素
     * @param key
     * @return
     */
    public <T extends Serializable> T  popList(String key) {

        Jedis redis =null;
        try {
            redis = getJedis();
            byte[] in_key = SafeEncoder.encode(key);
            return unserializable( redis.lpop(in_key));
        } finally {
            if (null != redis)
                freeConn(redis);
        }
    }

    /**
     * 将redis哈希表 key 中的域 field 的值设为 value 。
     * @param key
     * @param field
     * @param value
     * @return
     */
    public  <T extends Serializable> boolean putMap(String key, String field, T value) {

        boolean re = true;
        Jedis redis = null;
        Long newCount = (long) 0;
        try {
            redis = getJedis();
            byte[] in_key = SafeEncoder.encode(key);
            byte[] in_field = SafeEncoder.encode(field);
            newCount = redis.hset(in_key,in_field, serializable(value));
            re = newCount== 0 ? false : true;
        } finally {
            if (null != redis)
                freeConn(redis);
        }
        return re;
    }
    /**
     * 获取redis哈希表key中的域 field 的值。
     * @param key
     * @param field
     * @return
     */
    public <T extends Serializable> T getMap(String key,String field) {

        Jedis redis =null;
        try {
            redis = getJedis();
            byte[] in_key = SafeEncoder.encode(key);
            byte[] in_field = SafeEncoder.encode(field);
            return  unserializable(redis.hget(in_key, in_field));
        } finally {
            if (null != redis)
                freeConn(redis);
        }
    }

    /**
     * 删除redis中key的field。
     * @param key
     * @param field
     * @return
     */
    public boolean removeMap(String key,String field) {

        Jedis redis = null;
        Long newCount = (long) 0;
        boolean re = true;
        try {
            redis = getJedis();
            byte[] in_key = SafeEncoder.encode(key);
            byte[] in_field = SafeEncoder.encode(field);
            newCount = redis.hdel(in_key, in_field);
            re = newCount == 0 ? false : true;
            return re;
        } finally {
            if (null != redis)
                freeConn(redis);
        }
    }

    /**
     * 序列化
     *
     * @param t
     * @return
     */
    public  <T extends Serializable> byte[] serializable(T t) {
        if (t == null) {
            return null;
        }
        ByteArrayOutputStream baos = null;
        ObjectOutputStream oos = null;
        try {
            baos = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(baos);
            oos.writeObject(t);
            return baos.toByteArray();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (oos != null) {
                    oos.close();
                }
                if (baos != null) {
                    baos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * 反序列化
     *
     * @param b
     * @return
     */
    @SuppressWarnings("unchecked")
    public  <T extends Serializable> T unserializable(byte[] b) {
        if (b == null) {
            return null;
        }
        ByteArrayInputStream bais = null;
        ObjectInputStream ois = null;
        try {
            bais = new ByteArrayInputStream(b);
            ois = new ObjectInputStream(bais);
            return (T) ois.readObject();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (ois != null) {
                    ois.close();
                }
                if (bais != null) {
                    bais.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * 批量反序列化
     *
     * @param list
     * @return
     */
    @SuppressWarnings("unchecked")
    public  <T extends Serializable> List<T> unserializable(List<byte[]> list) {
        List<T> result = new ArrayList<T>();
        if (list == null || list.size() == 0) {
            return null;
        }
        for (byte[] b : list) {
            if (b != null) {
                result.add((T) unserializable(b));
            }
        }
        return result;
    }

    /**
     * 批量反序列化Hash
     * @param hash
     * @param <T>
     * @return
     */
    @SuppressWarnings("unchecked")
    public  <T extends Serializable> Map<String, T> unserializable(Map<byte[], byte[]> hash) {
        Map<String, T> result = new HashMap<String, T>();
        if (hash == null || hash.size() == 0) {
            return null;
        }
        for (Map.Entry<byte[], byte[]> e : hash.entrySet()) {
            if (e != null) {
                result.put(SafeEncoder.encode(e.getKey()), (T) unserializable(e.getValue()));
            }
        }
        return result;
    }

    public  JedisPool getPool() {
        return pool;
    }

    public  void setPool(JedisPool pool) {
        this.pool = pool;
    }
    
    
    
    /*********minglu baseredis begin*************************************************************/
    /**
     * 给定KEY的对象是否已经存在
     * @param key
     * @return
     */
    public boolean exists(String key){
        logger.info( ">>>> exists ---- is exists key ---- " + key);
        boolean re = true;
        Jedis jedis =null;
        try {
            jedis = pool.getResource();
            re = jedis.exists(key);
        } finally {
            pool.returnResource(jedis);
        }
        logger.info( "<<<< exists ---- is exists key ---- result: " + re);
        return re;
    }

    /**
     * redis保存key-value数据
     * @param key
     * @param value
     * @return
     */
    public boolean putKV(String key ,String value) {
        logger.info(">>>> putKV ----- key : {}----value : {}", key, value);
        boolean re = true;
        Jedis jedis =null;
        try {
            jedis = pool.getResource();
            jedis.set(key, value);
            re = true;
        } finally {
            pool.returnResource(jedis);
        }
        logger.info("<<<< putKV ----- key : {}----result : {}", key, re);
        return re;
    }

    /**
     * redis保存key-value数据, value为byte[]结构
     * @param key
     * @param value
     * @return
     */
    public boolean putKV(String key, byte[] value, int seconds) {
        logger.info(">>>> putKV ----- key : {}----value : {}", key, value);
        boolean re = true;
        Jedis jedis =null;
        try {
            jedis = pool.getResource();
            jedis.setex(key.getBytes(), seconds, value);
            re = true;
        } finally {
            pool.returnResource(jedis);
        }
        logger.info("<<<< putKV ----- key : {}----result : {}", key, re);
        return re;
    }

    /**
     * redis保存key-value数据
     * @param key
     * @param value
     * @param seconds 大于0表示为给定 key 设置生存时间，小于等于0表示未设置生存时间
     * @return
     */
    public boolean putKV(String key, String value, int seconds) {
        logger.info(">>>> putKV ---- life time: " + seconds + " -------key : {} ---", key);
        boolean re = true;
        Jedis jedis =null;
        try {
            jedis = pool.getResource();
            jedis.setex(key,seconds, value);
            re = true;
        } finally {
            pool.returnResource(jedis);
        }
        logger.info("<<<< putKV ----- key : {}----result : {}", key, re);
        return re;
    }

    /**
     * redis 将 key 的值设为 value ，当且仅当 key 不存在。若给定的 key 已经存在，则不做任何动作。
     * @param key
     * @param value
     * @return
     */
    public boolean putNxKV(String key ,String value) {
        logger.info(">>>> putNxKV ----- key : " + key);
        boolean re = true;
        Jedis jedis =null;
        try {
            jedis = pool.getResource();
            long set = jedis.setnx( key, value);
            re = set > 0 ? true : false;
        } finally {
            pool.returnResource(jedis);
        }
        logger.info("<<<< putNxKV ----- key : {}----result : {}", key, re);
        return re;
    }

    /**
     * 返回redis 中 key 所关联的字符串值。
     * @param key
     * @return
     */
    public String getKV(String key) {
        logger.info(">>>> getKV ----- key : " + key);
        String re = null;
        Jedis jedis =null;
        try {
            jedis = pool.getResource();
            re = jedis.get(key);
        } finally {
            pool.returnResource(jedis);
        }
        logger.info("<<<< getKV ----- key : {}----result : {}", key, "success!");
        return re;
    }

    /**
     * 删除redis中给定的 key 。不存在的 key 会被忽略。
     * @param key
     * @return 删除条数
     */
    public boolean removeKV(String key) {
        logger.info(">>>> removeKV ----- key : " + key);
        Jedis jedis =null;
        long re = 0;
        try {
            jedis = pool.getResource();
            re = jedis.del(key);
        } finally {
            pool.returnResource(jedis);
        }
        logger.info("<<<< removeKV ----- key : {}----result : {}", key, re);
        return true;
    }

    /**
     * 删除redis中给定的一个或者多个key 。不存在的 key 会被忽略。
     * @param keys
     * @return 删除条数
     */
    public String removeKV(String... keys) {
        logger.info(">>>> removeKV ----- keys : " + keys);
        String re = null;
        Jedis jedis =null;
        try {
            jedis = pool.getResource();
            long s = jedis.del(keys);
            re = s + "";
        } finally {
            pool.returnResource(jedis);
        }
        logger.info("<<<< removeKV ----- keys : {}----result : {}", keys, re);
        return re;
    }


    /**
     * 将一个或多个值 value 插入到redis列表 key 的表头
     * @param key
     * @param values
     * @return
     */
    public boolean putList(String key, String... values) {
        logger.info(">>>> putList ----- key : {} ---- values : {}", key, JsonUtil.toJson(values));
        boolean re = true;
        Jedis jedis =null;
        try {
            jedis = pool.getResource();
            for(String data : values){
                jedis.lpush(key , data);
            }
            re = true;
        } finally {
            pool.returnResource(jedis);
        }
        logger.info("<<<< putList ----- key : {}----result : {}", key, re);
        return re;
    }

    /**
     * 返回redis列表 key 中的第一个元素。不移除。
     * @param key
     * @return
     */
    public String getListFirstValue(String key) {
        logger.info(">>>> getList ----- get first value ----- key : {} ", key);
        String re = null;
        Jedis jedis =null;
        try {
            jedis = pool.getResource();
            String value = jedis.lindex(key, 0);
            re = value;
        } finally {
            pool.returnResource(jedis);
        }
        logger.info("<<<< getList ----- get first value ----- key : {}----result : {}", key, re);
        return re;
    }

    /**
     * 移除并返回redis列表 key 中的第一个元素
     * @param key
     * @return
     */
    public String popListFirstValue(String key) {
        logger.info(">>>> popList ----- pop first value ----- key : {} ", key);
        String re = null;
        Jedis jedis =null;
        try {
            jedis = pool.getResource();
            String value = jedis.lpop(key);
            re = value;
        } finally {
            pool.returnResource(jedis);
        }
        logger.info("<<<< popList ----- pop first value ----- key : {}----result : {}", key, re);
        return re;
    }

    /**
     * 将redis哈希表 key 中的域 field 的值设为 value 。
     * @param key
     * @param field
     * @param value
     * @return
     */
    public boolean putMap(String key, String field, String value) {
        logger.info(">>>> putMap ----- put value to key's field ----- key : " + key + " --- field : " + field + " --- value : " + value);
        boolean re = true;
        Jedis jedis = null;
        Long newCount = (long) 0;
        try {
            jedis = pool.getResource();
            newCount = jedis.hset(key, field, value);
            re = newCount== 0 ? false : true;
        } finally {
            pool.returnResource(jedis);
        }
        logger.info("<<<< putMap ----- put value to key's field ----- key : {}----result : {}", key, re);
        return re;
    }

    /**
     * 同时将多个 field-value (域-值)对设置到哈希表 key 中。 会覆盖哈希表中已存在的域。
     * @param key
     * @param map
     * @return
     */
    public boolean putMap(String key,Map map) {
        logger.info(">>>> putMap ----- put whole map ----- key : {} --- value : {}", key, JsonUtil.toJson(map));
        Jedis jedis = null;
        boolean re = true;
        try {
            String res;
            jedis = pool.getResource();
            res = jedis.hmset(key, map);
            re = "OK".equalsIgnoreCase(res) ? false : true;
        } finally {
            pool.returnResource(jedis);
        }
        logger.info("<<<< putMap ----- put whole map ----- key : {}----result : {}", key, re);
        return re;
    }

    /**
     * 同时将多个 field-value (域-值)对设置到哈希表 key 中。 会覆盖哈希表中已存在的域。
     * @param key
     * @param map
     * @param seconds 大于0表示为给定 key 设置生存时间，小于等于0表示未设置生存时间
     * @return
     */
    public boolean putMap(String key, Map map, int seconds) {
        logger.info(">>>> putMap ----- put whole map with lifetime ----- key : {} --- value : {} --- lifetime : " + seconds , key, JsonUtil.toJson(map));
        Jedis jedis = null;
        boolean re = true;
        try {
            String res = null;
            jedis = pool.getResource();
            res = jedis.hmset(key, map);
            if(seconds > 0) {
                jedis.expire(key, seconds);
            }
            re = res == "OK" ? false : true;
        } finally {
            pool.returnResource(jedis);
        }
        logger.info("<<<< putMap ----- put whole map ----- key : {}----result : {}", key, re);
        return re;
    }

    /**
     * 获取redis哈希表key中的域 field 的值。
     * @param key
     * @param field
     * @return
     */
    public String getMapString(String key,String field) {
        logger.info(">>>> getMap ----- get key's field value ----- key : {} --- field : {}", key, field);
        Jedis jedis = null;
        String re = null;
        try {
            jedis = pool.getResource();
            re = jedis.hget(key, field);
        } finally {
            pool.returnResource(jedis);
        }
        logger.info("<<<< getMap ----- get key's field value ----- key : {}----result : {}", key, "success!");
        return re;
    }

    /**
     * 获取redis哈希中多个field的value
     * @param key
     * @param fields
     * @return
     */
    public List<String> getMMap(String key, String... fields) {
        logger.info(">>>> getMMap ----- get key's many field values ----- key : {} --- fields : {}", key, JsonUtil.toJson(fields));
        List<String> values = new ArrayList<String>();
        Jedis jedis = null;
        try {
            jedis = pool.getResource();
            values = jedis.hmget(key, fields);
        } finally {
            pool.returnResource(jedis);
        }
        logger.info("<<<< getMMap ----- get key's many field values ----- key : {} --- result : {}", key, "success!");
        return values;
    }

    /**
     * 获取redis中的整个哈希
     * @param key
     * @return
     */
    public Map<String, String> getMapAll(String key) {
        logger.info(">>>> getMapAll ----- get whole map ----- key : {} ", key);
        Jedis jedis = null;
        Map<String, String> map = null;
        try {
            jedis = pool.getResource();
            map = jedis.hgetAll(key);
            logger.info("<<<< getMapAll ----- get whole map ----- key : {} --- result : {}", key, "success!");
            return map.size() == 0 ? null : map;
        } finally {
            pool.returnResource(jedis);
        }

    }

    /**
     * 为哈希表 key 中的域 field 的值加上增量 value 。
     * 增量也可以为负数，相当于对给定域进行减法操作。
     * 如果 key 不存在，一个新的哈希表被创建并执行 HINCRBY 命令。
     * 如果域 field 不存在，那么在执行命令前，域的值被初始化为 0 。
     *
     * @param key
     * @param field
     * @param value
     * @return
     */
    public Long incredMap(String key,String field,int value ) {
        logger.info(">>>> incredMap ----- increase map field's value ----- key : " + key + " --- field : " + field + " --- value : " + value);
        Jedis jedis =null;
        Long newCount = Long.parseLong("-1");
        try {
            jedis = pool.getResource();
            newCount = jedis.hincrBy(key,field, value);
            logger.info("<<<< incredMap ----- increase map field's value ----- key : {} --- field : {} --- result : " + newCount, key, field);
            return newCount;
        } finally {
            pool.returnResource(jedis);
        }

    }


    /**
     * 给redis中的多个哈希设置生存时间
     * @param keys
     * @param fields
     * @param value
     * @param seconds
     * @return
     */
    public boolean putMapExiperse(String[] keys,String[] fields,String[] value, int[] seconds) {
        Jedis jedis = null;

        try {
            jedis = pool.getResource();
            Pipeline plin = jedis.pipelined() ;
            for(int i = 0 ;i < keys.length;i++ ){
                plin.hset(keys[i], fields[i], value[i]);
                plin.expire(keys[i], seconds[i]);
            }
            List<Object> r = plin.syncAndReturnAll();
            return r == null ? false : true;
        } finally {
            pool.returnResource(jedis);
        }
    }

    /**
     * 获取有序集合中所有的数据
     * @param key
     * @return
     */
    public Set<String> getSortSet(String key) {
        logger.info(">>>> getSortSet ----- get sort set ----- key : {}", key);
        Jedis jedis =null;
        try {
            jedis = pool.getResource();
            Set<String> res = jedis.zrangeByScore(key, 0, System.currentTimeMillis());
            return res.size() == 0 ? null : res;
        } finally {
            pool.returnResource(jedis);
        }
    }

    /**
     * 向有序集合中放入数据，优先级按照时间排序
     * @param key
     * @param value
     * @return
     */
    public boolean putSortSet(String key,String value) {
        Jedis jedis =null;
        try {
            jedis = pool.getResource();
            Long result = jedis.zadd(key, System.currentTimeMillis(), value);
            return  true;
        } finally {
            pool.returnResource(jedis);
        }
    }

    /**
     * 向有序集合中放入数据，自定义优先级
     * @param key
     * @param value
     * @param proi 优先级
     * @return
     */
    public boolean putSortSet(String key,String value,long proi) {
        Jedis jedis =null;
        try {
            jedis = pool.getResource();
            Long result = jedis.zadd(key, proi, value);
            return  true;
        } finally {
            pool.returnResource(jedis);
        }
    }

    /**
     * 移除有序集 key 中的一个或多个成员，不存在的成员将被忽略。
     * @param key
     * @param values
     * @return
     */
    public long removeSortSet(String key,String... values) {
        Jedis jedis =null;
        try {
            jedis = pool.getResource();
            Long res = jedis.zrem(key, values)   ;
            return  res;
        } finally {
            pool.returnResource(jedis);
        }
    }

    /**
     * 设置key的生存时间
     * @param key
     * @param seconds
     * @return
     */
    public boolean setExiperse(String key,int seconds) {
        logger.info(">>>> setExiperse ----- set key's lifetime ----- key : {}", key);
        Jedis jedis =null;
        try {
            jedis = pool.getResource();
            long r =  jedis.expire(key, seconds);
            if(r>0){
                logger.info( "<<<< setExiperse---- set key's lifetime ----- key : {} --- seconds : {}", key, seconds);
                return true;
            }else{
                return false;
            }
        } finally {
            pool.returnResource(jedis);
        }
    }

    public long ttl(String key) {
        Jedis jedis = null;
        try {
            jedis = pool.getResource();
            return jedis.ttl(key);
        } finally {
            pool.returnResourceObject(jedis);
        }

    }

    /**
     * 添加1个经纬度到redis
     * @param key
     * @param longitude 精度
     * @param latitude 维度
     * @param member 位置名称
     * @return
     */
    public long addGeoCoordinate(String key,double longitude, double latitude,String member) {
        logger.info(">>>> addGeoCoordinate ----- set one  ----- key : {}", key);
        Jedis jedis = null;
        try {
            jedis = pool.getResource();
            GeoCoordinate geoCoordinate = new GeoCoordinate(longitude, latitude);
            Long r = jedis.geoadd(key, longitude, latitude, member);
            return r;
        } finally {
            pool.returnResource(jedis);
        }
    }

    /**
     * 添加n个经纬度到redis
     * @param key
     * @param memberCoordinateMap  key:member（经纬度名称）
     * @return
     */
    public long addGeoCoordinate(String key, Map<String, Coordinate> memberCoordinateMap){
        logger.info(">>>> addGeoCoordinate ----- set memberCoordinateMap ----- key : {}", key);
        Jedis jedis = null;
        try {
            jedis = pool.getResource();
            Map<String,GeoCoordinate> map = new HashMap<>();
            for (Map.Entry<String, Coordinate> entry : memberCoordinateMap.entrySet())
            {
                Coordinate coordinate =entry.getValue();
                GeoCoordinate geoCoordinate =new GeoCoordinate(coordinate.getLongitude(),coordinate.getLatitude());
                map.put(entry.getKey(),geoCoordinate);
            }
            Long r = jedis.geoadd(key, map);
            return r;
        } finally {
            pool.returnResource(jedis);
        }
    }


    /**
     * 根据member1 member2 的经纬度信息计算二者之间的距离 返回相差多少米
     * @param key
     * @param member1 需要geoadd添加
     * @param member2 需要geoadd添加
     * @return
     */
    public double geodist(String key,String member1,String member2)
    {
        logger.info(">>>> geodist ----- set ----- key : {}", key);
        Jedis jedis = null;
        try {
            jedis = pool.getResource();

            Double r = jedis.geodist(key,member1,member2, GeoUnit.M);
            return r;
        } finally {
            pool.returnResource(jedis);
        }
    }


}
